package com.example.commen.utile

import android.app.AppOpsManager
import android.app.Application
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.media.AudioAttributes
import android.os.Build
import android.os.PowerManager
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.net.toUri
import com.example.commen.R
import com.example.commen.base.UCApplication
import com.example.commen.resource.CommentContect.filePath.Companion.notificationMusic

/*** @author phz
 * @introduction 通知栏工具类
 * @see [https://developer.android.google.cn/training/notify-user/build-notification]
 */
class NotificationUtils(application: Application) {
    init { //获取NotificationManager对象
        manager = application.getSystemService(Service.NOTIFICATION_SERVICE) as NotificationManager
    }



    /*** @param title 通知标题
     * @param msg      通知消息
     * @param channelId    渠道id
     * @param channelName 渠道名
     * @param requestId  区分不同的通知，这个id用于更新(也可以叫覆盖)和移除某个通知  一个独特的Integer，比如使用系统时间{int requestId = (int) System.currentTimeMillis();}*
     * @param smallIcon     小图标* @param largeIcon
     * 大图标* @param pendingIntent 指定意图和执行目标动作的Intent，往往用于通知点击跳转
     */
    fun showNotification(
        title: String, msg: String, channelId: String, channelName: String,
        requestId: Int, smallIcon: Int, largeIcon: Bitmap, pendingIntent: PendingIntent
    ) {
        var pm = UCApplication.getContext().getSystemService(Context.POWER_SERVICE) as PowerManager;
        var wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Notification :");
        wl.acquire(1*6*1000L /*10 秒*/)
        //sdk26以上（8.0）需要指定通道
        notificationChannel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
        //设置可以绕过请勿打扰模式
        notificationChannel.setBypassDnd(true)
        //可否绕过请勿打扰模式
        notificationChannel.canBypassDnd()
        //锁屏显示通知
        notificationChannel.lockscreenVisibility = Notification.VISIBILITY_SECRET
        //是否会闪光
        notificationChannel.shouldShowLights()
        //闪光
        notificationChannel.enableLights(true)
        //指定闪光时的灯光颜色，低版本在builder上通过setLights方法设置{builder.setLights(Color.GREEN, 1000, 1000);}
        notificationChannel.lightColor = Color.RED
        //此通道桌面launcher消息角标不显示
        notificationChannel.setShowBadge(false)
        //是否允许震动
        notificationChannel.enableVibration(true)
        //震动模式，第一次100ms，第二次100ms，第三次200ms，低版本在Notification.Builder上设置{builder.setVibrate(new long[]{200, 1000});}
        notificationChannel.vibrationPattern = longArrayOf(100, 100, 200)
        //获取系统通知响铃声音的配置
//        notificationChannel.audioAttributes
        val audioAttributes = AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .setUsage(AudioAttributes.USAGE_NOTIFICATION)
            .build()
        notificationChannel.setSound(notificationMusic.toUri(), audioAttributes)

        //获取通知渠道组notificationChannel.getGroup();
        /*** 先建一个渠道 */
        manager.createNotificationChannel(notificationChannel)
        builder = NotificationCompat.Builder(UCApplication.getBaseApplication(), channelId)
        //设置标题
        builder.setContentTitle(title)
        //设置文本
        builder.setContentText(msg)
        builder.setSmallIcon(smallIcon, 10000)
        builder.setPriority(NotificationCompat.PRIORITY_MAX)
        builder.setWhen(System.currentTimeMillis())
        builder.setLargeIcon(largeIcon)
        builder.setContentIntent(pendingIntent)
        //点击通知后后自动取消
        builder.setAutoCancel(true)
        //发送通知
        manager.notify(requestId, builder.build())

    }

    // 
    /***
     * 通道适配
     * @notice 调用时机尽可能早，比如在各渠道sdk初始化成功之前就创建其对应的通道，才能正常接收消息
     */
    @RequiresApi(Build.VERSION_CODES.O)
    fun initNotificationChannel(id: String?, name: String?) {
        //8.0通道适配
        val channel = NotificationChannel(id, name, NotificationManager.IMPORTANCE_HIGH)
        val notificationManager = UCApplication.getBaseApplication().getSystemService(Service.NOTIFICATION_SERVICE) as NotificationManager
        //创建好通道后，通过代码createNotificationChannel仅仅只能更新其name/description以及对importance进行降级，其余配置均无法更新。
        // 反复调用createNotificationChannel是安全的，因为创建现有通知渠道不会执行任何操作。
        notificationManager.createNotificationChannel(channel)
    }

    /*** 应用是否允许通知* @param context* @return */
    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    fun isNotificationEnabled(context: Context): Boolean {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            //8.0手机以上
            if ((context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager).importance == NotificationManager.IMPORTANCE_NONE) {
                return false
            }
        }
        val CHECK_OP_NO_THROW = "checkOpNoThrow"
        val OP_POST_NOTIFICATION = "OP_POST_NOTIFICATION"
        val mAppOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
        val appInfo = context.applicationInfo
        val pkg = context.applicationContext.packageName
        val uid = appInfo.uid
        var appOpsClass: Class<*>? = null
        try {
            appOpsClass = Class.forName(AppOpsManager::class.java.name)
            val checkOpNoThrowMethod = appOpsClass.getMethod(CHECK_OP_NO_THROW, Integer.TYPE, Integer.TYPE, String::class.java)
            val opPostNotificationValue = appOpsClass.getDeclaredField(OP_POST_NOTIFICATION)
            val value = opPostNotificationValue[Int::class.java] as Int
            return (checkOpNoThrowMethod.invoke(mAppOps, value, uid, pkg) as Int == AppOpsManager.MODE_ALLOWED)
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return false
    }

    companion object {
        private var mInstance: NotificationUtils? = null

        /*** 通知栏管理器 */
        private lateinit var manager: NotificationManager

        /*** 通知栏频道设置 */
        private lateinit var notificationChannel: NotificationChannel

        /*** 通知构造器* 在使用最新通知 API 功能的同时仍然支持旧版设备，不需要您编写代码检查Api级别。* 需要注意调用某个方法的时候不能保作所有设备都有这个功能，可能出现空操作。比如addAction只会在Api 16以上生效。 */
        private lateinit var builder: NotificationCompat.Builder

        val instance: NotificationUtils?
            /*** 单一实例 */
            get() {
                if (mInstance == null) {
                    mInstance = NotificationUtils(UCApplication.getBaseApplication())
                }
                return mInstance
            }
    }
}

